%{
#include <stdio.h>
#include <math.h>
extern int yylex(void);
extern char *yytext;
extern int yylineno;
void yyerror (char *s);
%}

%union
{
   float real;
   int entero;
   char caracter;
   char* string; 
}
%debug
%error-verbose
%locations
%start Accion

/*INICIALES*/
%token <string> TKN_CREATE
%token <string> TKN_DROP
%token <string> TKN_ALTER
%token <string> TKN_TRUNCATE

/*TIPOS DE VARIABLE*/
%token <string> TKN_TIPO1
%token <string> TKN_TIPO2
%token <string> TKN_TIPO3   
	    
/*CONSTRAINTS*/
%token <string> TKN_CHECK 
%token <string> TKN_UNIQUE
%token <string> TKN_NOTNULL
%token <string> TKN_PRIMARYKEY
%token <string> TKN_FOREIGNKEY
%token <string> TKN_DEFAULT
%token <string> TKN_IDENTITY
%token <string> TKN_REFERENCES
%token <string> TKN_CONSTRAINT
%token <string> TKN_NOACTION
%token <string> TKN_SETDEFAULT
%token <string> TKN_CASCADE
%token <string> TKN_SETNULL 
%token <string> TKN_ONDELETE
%token <string> TKN_ONUPDATE

/*COMPARACION*/
%token TKN_MENORQUE
%token TKN_MAYORQUE
%token TKN_IGUALDAD
%token <string> TKN_MAYOROIGUAL
%token <string> TKN_MENOROIGUAL
%token <string> TKN_DIFERENTE

/*EXTRA*/
%token <string> TKN_AND
%token <string> TKN_OR
%token <string> TKN_XOR
%token <string> TKN_NOT
%token <string> TKN_ON
%token <string> TKN_AS
%token <string> TKN_COLUMN
%token <string> TKN_ADD

%token <real> TKN_NUM
%token <entero> TKN_INTNUM
%token TKN_IGUAL
%token TKN_COMA
%token TKN_PTOCOMA
%token TKN_LITERAL
%token TKN_MULT
%token TKN_DIV
%token TKN_MAS
%token TKN_MENOS
%token TKN_MOD
%token TKN_LP
%token TKN_RP
%token <string> TKN_TIPO
%token <char> TKN_ADICIONAL
%token <string> TKN_TABLE
%token <string> TKN_INDEX
%token <string> TKN_DATABASE
%token <string> TKN_PROCEDURE
%token <string> TKN_TRIGGER
%token <string> TKN_NOMBRE
%token <string> TKN_LITERAL


%%
Accion
		:create SigueCreate Denuevo
		|drop SigueDrop
		|alter SigueAlter
		|truncate table nombre
|error {printf("---\nERROOOOOOOOOOOOOOOOORRRR1\n");}
;
SigueCreate
		:table nombre lp Desicion rp ptocoma
		|unique index nombre on nombre lp uno_o_varios rp
		|index nombre on nombre lp uno_o_varios rp
|error {printf("---\nERROOOOOOOOOOOOOOOOORRRR2\n");}
;
Denuevo	:{printf("\nFIN!\n");}
		|Accion {printf("\nFIN!\n");}

		;

SigueDrop
		:table nombre
		|index nombre
		|database nombre
|error {printf("---\nERROOOOOOOOOOOOOOOOORRRR4\n");}
;
SigueAlter
		:table nombre Alteracion
		|index nombre
		|database nombre
|error {printf("---\nERROOOOOOOOOOOOOOOOORRRR5\n");}
;
Alteracion
		:add nombre data_type
		|drop column nombre 
		|alter column nombre data_type
|error {printf("---\nERROOOOOOOOOOOOOOOOORRRR6\n");}
;
uno_o_varios
		:nombre uno_o_varios2
|error {printf("---\nERROOOOOOOOOOOOOOOOORRRR7\n");}
		;
uno_o_varios2
		:
		|coma uno_o_varios
|error {printf("---\nERROOOOOOOOOOOOOOOOORRRR8\n");}
;
Desicion  : 
		nombre data_type op_adicional Desicion2
		|nombre data_type Desicion2
		|primarykey lp uno_o_varios rp Desicion2
		|foreignkey lp uno_o_varios rp references nombre lp uno_o_varios rp foreign_accion Desicion2
		|constraint nombre unique lp uno_o_varios rp Desicion2
		|constraint nombre primarykey lp uno_o_varios rp Desicion2
		|constraint nombre foreignkey lp uno_o_varios rp references nombre lp uno_o_varios rp foreign_accion Desicion2
|error {printf("---\nERROOOOOOOOOOOOOOOOORRRR9\n");}
;
Desicion2 
		: 
		|coma Desicion
		|ptocoma 
|error {printf("---\nERROOOOOOOOOOOOOOOOORRRR10\n");}
;
data_type
	    	:tipo1
		|tipo2 par_tipo2
		|tipo3 lp intnum rp
|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR11\n");}
	    ;
par_tipo2	:
		|lp par_tipo2 rp
		|intnum prueba 
		|error {yyerrok;}
		
;
prueba	:
		|coma intnum
		|error intnum
		|coma error
		|error {yyerrok;}
;
		 
op_adicional
		:
		|check lp expresion rp op_adicional
		|unique op_adicional
		|notnull op_adicional
		|primarykey op_adicional
		|default literal op_adicional
		|default intnum op_adicional
		|identity lp intnum coma intnum rp op_adicional
		|references nombre lp nombre rp foreign_accion op_adicional 
|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR12\n");}
;
foreign_accion
			:
			|ondelete foreign_mod
			|onupdate foreign_mod
|error {printf("---\nERROOOOOOOOOOOOOOOOORRRR13\n");}
foreign_mod
			:
			|noaction
			|setdefault
			|cascade
			|setnull
|error {printf("---\nERROOOOOOOOOOOOOOOOORRRR14\n");}
	
expresion
		:nombre compara intnum op_logico
		|nombre compara literal op_logico
		|nombre compara aritmetica
|error {printf("---\nERROOOOOOOOOOOOOOOOORRRR15\n");}
		;
aritmetica	
		:lp aritmetica2 rp aritmetica2
		|intnum aritmetica2
|error {printf("---\nERROOOOOOOOOOOOOOOOORRRR16\n");}
aritmetica2
		:
		|op_aritmetico aritmetica2
		|nombre aritmetica2
		|aritmetica

/**********TERMINALES******/
create 
		:TKN_CREATE
		|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR18\n");}
drop		
		:TKN_DROP
		|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR19\n");}
alter		
		:TKN_ALTER

truncate	
		:TKN_TRUNCATE

tipo1		/*Tipos sin parametros*/
		:TKN_TIPO1	
;
tipo2		/*Tipos con O sin parametros*/
		:TKN_TIPO2
		|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR23\n");}
;
tipo3:	/*Tipos con 1 parametro*/
		|TKN_TIPO3

   
check:		TKN_CHECK 
			|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR25\n");}
unique:		TKN_UNIQUE
			|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR26\n");}
notnull:		TKN_NOTNULL

primarykey:	TKN_PRIMARYKEY
			|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR28\n");}
foreignkey:	TKN_FOREIGNKEY

default:		TKN_DEFAULT
			|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR30\n");}
identity:		TKN_IDENTITY

references:	TKN_REFERENCES
			|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR32\n");}
constraint:	TKN_CONSTRAINT
			|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR33\n");}
;
noaction:		TKN_NOACTION

setdefault:	TKN_SETDEFAULT

cascade:		TKN_CASCADE

setnull:		TKN_SETNULL 

ondelete:		TKN_ONDELETE
			|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR38\n");}
onupdate: 		TKN_ONUPDATE

on:		TKN_ON
		|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR41\n");}
/*as: 		TKN_AS
		|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR42\n");}*/
column: 	TKN_COLUMN
		|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR43\n");}
add:		TKN_ADD
		|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR44\n");}

intnum: 	TKN_INTNUM
		|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR45\n");}
coma:		TKN_COMA
		|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR462\n");}
ptocoma:	TKN_PTOCOMA
		|error intnum {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR47\n");}
lp:		TKN_LP
		|error {yyerrok;
printf("---\nERROOOOOOOOOOOOOOOOORRRR52\n");}
rp:		TKN_RP
		|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR53\n");}

table:	TKN_TABLE
		|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR55\n");}
index:	TKN_INDEX
		|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR56\n");}
database:	TKN_DATABASE

nombre:	TKN_NOMBRE
		|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR59\n");}
literal: 	TKN_LITERAL

op_logico
		:
		|TKN_AND 
		|TKN_OR 
		|TKN_XOR 
		|TKN_NOT 
		|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR61\n");}
		;
op_aritmetico
		:TKN_MAS
		|TKN_MENOS
		|TKN_MULT
		|TKN_DIV
		|TKN_MOD

compara
		:
TKN_IGUALDAD
|TKN_MAYORQUE
|TKN_MENORQUE
|TKN_DIFERENTE
|TKN_MENOROIGUAL
|TKN_MAYOROIGUAL
|error {yyerrok;printf("---\nERROOOOOOOOOOOOOOOOORRRR63\n");}
		;
%%

void yyerror(char *s)
{
   printf("Error: %s near by '%s' ON LINE:%d COL:%d \n", s,yytext,yylineno,yylloc.first_column);
}

int main()
{
   extern int yydebug;
   yydebug = 1;
   extern FILE*  yyin;
   yyin = fopen("filename", "r");
   yyparse();
   printf("Total Errors Encountered: %d. \n",yynerrs);
   return 0;
}
